<template>
  <div class="c-tree">
    <m-tree-node
      v-for="(item,index) in treeData"
      :key="item[nodeKey]"
      :nodeData="item"
      :index="index"
      :showExtraFile="showExtraFile"
      is-root
    />
  </div>
</template>
<script>
import { findNodeByValue, treeForEach } from '@/util/common';
import TreeNode from './TreeNode';

/**
 * 树节点结构
 * type TreeNode = {
 *  id:string, 唯一标识，可以通过nodeKey指定
 *  children:TreeNode[], 子节点
 *  expand: boolean, 是否展开
 * selected: boolean, 是否选中
 * 
 * //// 懒加载树特有属性
 * loaded: boolean, 是否已加载子节点（如果为false，在点击展开时会调用loadNodes去加载子节点）
 * loading: boolean, 是否正在加载子节点(当loading是true时，点击展开按钮不会重新加载子节点)
 * isLeaf: boolean, 是否为叶节点(叶节点没有展开按钮)
 * 
 * }

 */
export default {
  name: 'common-tree-m-tree',
  provide(){
    return {
      tree: this
    };

  },
  components: {
	  'm-tree-node': TreeNode,
    
  },
  props: {
    //// 树结构数据，[{label，id,children:[] , expand:boolean(是否展开), selected:boolean（是否选中）,parent?:TreeNode}]
	  treeData: Array, 

    //// todo
    showCheckbox: {
      type: Boolean,
      default: false
    },

    showExtraFile: {
      type: Boolean,
      default: true
    },

    //// node的唯一标识的key，默认为‘id’
    nodeKey: {
      type: String,
      default: 'id'
    },

    //// 默认选中项的id
    defaultCurrentKey: String,

    //// 是否懒加载树节点
    lazy: Boolean, 

    /**
     * 
     */
    //// 懒加载树节点方法，(curNode:TreeNode)=>Promise<treeNode[]>

    loadNodes: Function,
    sortByName: Boolean
  },

  data() {
    return {
      currentNode: undefined,
      expandNodeMap: new Map()
      
    };
  },
  computed: {

  },
  watch: {
    data: {
      immediate: true,
      handler(newData){
        console.log('immediate');
        this.expandNodeMap = new Map();
        treeForEach(newData || [], node => {
          if (node.expand){
            this.expandNodeMap.set(node[this.nodeKey], node);
          }
          if (node.selected){
            this.setCurrentNode(node);
          }
        });

      }
    }
  },
  created(){
    console.log('created');

    if (this.defaultCurrentKey){
      this.setCurrentKey(this.defaultCurrentKey);
    }

  },
  methods: {
    getCurrentKey(){
      return this.currentNode[this.nodeKey];

    },
    setCurrentKey(id){
      const nodeData = findNodeByValue(this.treeData, id, this.nodeKey);
      this.setCurrentNode(nodeData);
      
    },
    getCurrentNode(){
      return this.currentNode;
    },
    setCurrentNode(nodeData){
      if (this.currentNode){
        this.currentNode.selected = false;
      }
      this.currentNode = nodeData;
      if (nodeData){
        nodeData.selected = true;
      }
      
    },
    /**
     * 展开父节点，如果不传node则默认展开当前节点的父节点
     */
    async expandParentNode(node = this.currentNode){
      if (!node) return;
      let parent = node.parent;
      while (parent) {
  
        parent.expand = true;
        this.expandNodeMap.set(parent.nodeId, parent);

        parent =  parent.parent;
      }
    },

    async toggleExpand(nodeData){
      if ( nodeData.expand == false && this.lazy && !nodeData.loaded && !nodeData.isLeaf){
        if ( nodeData.loading ) return;
        nodeData.loading = true;
        const childNodes = await this.loadNodes(nodeData).finally(() => nodeData.loading = false);
        nodeData.children = childNodes;
        nodeData.loaded = true; 
        if (!childNodes || childNodes.length === 0){
          nodeData.isLeaf = true;
        }
      }
      nodeData.expand = !nodeData.expand;
      if (nodeData.expand){
        this.expandNodeMap.set(nodeData.nodeId, nodeData);
      } else {
        this.expandNodeMap.delete(nodeData.nodeId);

      }
      this.$emit('expand', nodeData);
    },
    bindParent(nodeDatas){
      treeForEach(nodeDatas, (node, parent) => {
        node.parent = parent;
      });

    },
    getExpandNodes(){
      return this.expandNodeMap;
    },

  }
};
</script>
<style lang="scss">
//// .c-tree {
//// }
</style>